<?php

class Crypt{
	protected $key = "";    //Public key

	private function keyED($txt,$encrypt_key)
	{
		$encrypt_key = md5($encrypt_key);
		$ctr=0;
		$tmp = "";
		for ($i=0;$i<strlen($txt);$i++)
		{
			if ($ctr==strlen($encrypt_key)){
				$ctr=0;
			}
			$tmp.= substr($txt,$i,1) ^ substr($encrypt_key,$ctr,1);
			$ctr++;
		}
		return $tmp;
	}

	public function encrypt($txt, $key="")
	{
		if(empty($key)){
			$key=$this->key;
		}
		srand((double)microtime()*1000000);
		$encrypt_key = md5(rand(0,32000));
		$ctr=0;
		$tmp = "";
		for ($i=0;$i<strlen($txt);$i++)
		{
			if ($ctr==strlen($encrypt_key)){
				$ctr=0;
			}
			$tmp.= substr($encrypt_key,$ctr,1) .
			(substr($txt,$i,1) ^ substr($encrypt_key,$ctr,1));
			$ctr++;
		}
		return $this->keyED($tmp,$key);
	}

	public function decrypt($txt, $key="")
	{
		if(empty($key)){
			$key=$this->key;
		}

		$txt = $this->keyED($txt,$key);
		$tmp = "";
		for ($i=0;$i<strlen($txt);$i++)
		{
			$md5 = substr($txt,$i,1);
			$i++;
			$tmp .= (substr($txt,$i,1) ^ $md5);
		}
		return $tmp;
	}

	public function setKey($key)
	{
		if(empty($key)){
			return null;
		}
		$this->key=$key;
	}

	public function getKey()
	{
		return $this->key;
	}

}








class YL_Security_Secoder {
	public static $seKey = 'accessCode';
	public static $expire = 600;				// 10 minutes
	/**
	 * 验证码中使用的字符，01IO2Z容易混淆，建议不用
	 *
	 * @var string
	 */
	public static $codeSet = '346789ABCDEFGHIJKLMNOPQRTUVWXYZ';
	public static $fontSize = 27;
	public static $useCurve = false;
	public static $useNoise = true;
	public static $imageH = 0;
	public static $imageL = 0;
	public static $length = 4;
	public static $bg = array(243, 251, 254);

	protected static $_image = null;
	protected static $_color = null;

	public static function entry() {
		// 图片宽(px)
		self::$imageL || self::$imageL = self::$length * self::$fontSize * 1.5 + self::$fontSize*1.5;
		// 图片高(px)
		self::$imageH || self::$imageH = self::$fontSize * 2;
		// 建立一幅 self::$imageL x self::$imageH 的图像
		self::$_image = imagecreate(self::$imageL, self::$imageH);
		// 设置背景
		imagecolorallocate(self::$_image, self::$bg[0], self::$bg[1], self::$bg[2]);
		// 验证码字体随机颜色
		self::$_color = imagecolorallocate(self::$_image, mt_rand(1,120), mt_rand(1,120), mt_rand(1,120));
		// 验证码使用随机字体
		$ttf = dirname(__FILE__) . '/checkcodettfs/' . mt_rand(1, 4) . '.ttf';

		if (self::$useNoise) {
			// 绘杂点
			self::_writeNoise();
		}
		if (self::$useCurve) {
			// 绘干扰线
			self::_writeCurve();
		}

		// 绘验证码
		$code = array(); // 验证码
		$codeNX = 0; // 验证码第N个字符的左边距
		for ($i = 0; $i<self::$length; $i++) {
			$code[$i] = self::$codeSet[mt_rand(0, 27)];
			$codeNX += mt_rand(self::$fontSize*1.2, self::$fontSize*1.6);
			// 写一个验证码字符
			imagettftext(self::$_image, self::$fontSize, mt_rand(-40, 70), $codeNX, self::$fontSize*1.5, self::$_color, $ttf, $code[$i]);
		}

		isset($_SESSION) || session_start();
		$_SESSION[self::$seKey]['code'] = join('', $code); // 把校验码保存到session
		$_SESSION[self::$seKey]['time'] = time();  // 验证码创建时间

		header('Cache-Control: private, max-age=0, no-store, no-cache, must-revalidate');
		header('Cache-Control: post-check=0, pre-check=0', false);
		header('Pragma: no-cache');
		header("content-type: image/png");

		// 输出图像
		imagepng(self::$_image);
		imagedestroy(self::$_image);
	}

	protected static function _writeCurve() {
		$A = mt_rand(1, self::$imageH/2);                  // 振幅
		$b = mt_rand(-self::$imageH/4, self::$imageH/4);   // Y轴方向偏移量
		$f = mt_rand(-self::$imageH/4, self::$imageH/4);   // X轴方向偏移量
		$T = mt_rand(self::$imageH*1.5, self::$imageL*2);  // 周期
		$w = (2* M_PI)/$T;

		$px1 = 0;  // 曲线横坐标起始位置
		$px2 = mt_rand(self::$imageL/2, self::$imageL * 0.667);  // 曲线横坐标结束位置
		for ($px=$px1; $px<=$px2; $px=$px+ 0.9) {
			if ($w!=0) {
				$py = $A * sin($w*$px + $f)+ $b + self::$imageH/2;  // y = Asin(ωx+φ) + b
				$i = (int) ((self::$fontSize - 6)/4);
				while ($i > 0) {
					imagesetpixel(self::$_image, $px + $i, $py + $i, self::$_color);  // 这里画像素点比imagettftext和imagestring性能要好很多
					$i--;
				}
			}
		}

		$A = mt_rand(1, self::$imageH/2);                  // 振幅
		$f = mt_rand(-self::$imageH/4, self::$imageH/4);   // X轴方向偏移量
		$T = mt_rand(self::$imageH*1.5, self::$imageL*2);  // 周期
		$w = (2* M_PI)/$T;
		$b = $py - $A * sin($w*$px + $f) - self::$imageH/2;
		$px1 = $px2;
		$px2 = self::$imageL;
		for ($px=$px1; $px<=$px2; $px=$px+ 0.9) {
			if ($w!=0) {
				$py = $A * sin($w*$px + $f)+ $b + self::$imageH/2;  // y = Asin(ωx+φ) + b
				$i = (int) ((self::$fontSize - 8)/4);
				while ($i > 0) {
					imagesetpixel(self::$_image, $px + $i, $py + $i, self::$_color);  // 这里(while)循环画像素点比imagettftext和imagestring用字体大小一次画出（不用这while循环）性能要好很多
					$i--;
				}
			}
		}
	}

	protected static function _writeNoise() {
		for($i = 0; $i < 10; $i++){
			$noiseColor = imagecolorallocate(
			self::$_image,
			mt_rand(150,225),
			mt_rand(150,225),
			mt_rand(150,225)
			);
			for($j = 0; $j < 5; $j++) {
				imagestring(
				self::$_image,
				5,
				mt_rand(-10, self::$imageL),
				mt_rand(-10, self::$imageH),
				self::$codeSet[mt_rand(0, 27)],
				$noiseColor
				);
			}
		}
	}

	public static function check($code) {
		$result = false;
		
		if(empty($code) || empty($_SESSION[self::$seKey])) {
			$result = false;		echo 'no data';
		}else if(time() - $_SESSION[self::$seKey]['time'] > self::$expire) {
			$result = false;  		echo 'expire';
		}else{
			$result = (strtolower($code) == strtolower($_SESSION[self::$seKey]['code']));
		}
		
		unset($_SESSION[self::$seKey]);
		return $result;
	}
}











class Util {
	protected static $_msgs = null;

	public static function parseUrl($url)
	{
		if(strpos($url, 'https://') !== 0){
			$url = 'http://' . str_replace('http://', '', $url);
		}
		 
		$url = iconv('', 'utf-8', $url);
		$urlParsed = parse_url(strtolower($url));
		if(isset($urlParsed['query'])){
			parse_str($urlParsed['query'], $urlParsed['query']);
		}
		 
		return $urlParsed;
	}

	public static function againstBannedWords($contents)
	{
		$findWords = array();
		if(is_object(Model_Config::one()))
		{
			$findWords = Model_Config::one()->keyword;
		}
		if(count($findWords) >0 )
		{
			$replaceWords = array();
			$replaceWords =  array_pad($replaceWords, count($findWords), '');

			$contents_end = str_ireplace($findWords, $replaceWords, $contents);
			if($contents === $contents_end)
			{
				$contents = true;
			}
			else{
				$contents = false;//"Your comment will be reviewed by our moderators. Thank you.";
			}
			return $contents;
		}
		else{
			return true;
		}
	}


	/**
	 * @param array/string $htmlTags html tag, example: array('img' or 'a' .eg)
	 * @param string $content content
	 * @param string/bool/array $isSelfEnd <br />
	 * &nbsp;&nbsp;&nbsp;&nbsp;
	 * default - 'auto', it takes the these htmlTag as self-closing tag: 'img', 'br', 'script', 'hr', 'input', 'link', 'meta', 'area', 'base', 'basefont', 'frame', 'col'<br />
	 * @return array $ret
	 * <br />
	 * )
	 */
	public static function htmlRegCollection($htmlTags = '', $content, $isSelfEnds = 'auto', $trimResult = true, $enCoding = 'utf-8')
	{
		$matchesArr = array();
		$matchKey = array(
		0 => 'ELEMENT_ENTIRE',
		1 => 'ELEMENT_START_TAG',
		2 => 'ELEMENT_INNER',
		3 => 'ELEMENT_END_TAG'
		);
		if(is_string($htmlTags)){
			$htmlTags = array($htmlTags);
		}
		if(!is_array($isSelfEnds)){
			$isSelfEnds = array($isSelfEnds);
		}
		$isSelfEnds = array_pad($isSelfEnds, count($htmlTags), 'auto');
		foreach($htmlTags as $htmlTagCount => $htmlTag){
			$isSelfEnd = $isSelfEnds[$htmlTagCount];
			if($isSelfEnd == 'auto'){
				if(in_array(strtolower($htmlTag), array(
	    			'img', 'br', 'script', 'hr', 'input', 'link', 'meta', 'area', 'base', 'basefont', 'frame', 'col'
	    			))){
	    				$isSelfEnd = true;
	    			}else{
	    				$isSelfEnd = false;
	    			}
			}
			if($isSelfEnd){
				$reg = "/<$htmlTag"."[\s\S]*?\/?>/i";
			}else{
				$reg = "/(<$htmlTag"."[\s\S]*?>)([\s\S]*?)(<\/$htmlTag>)/i";
			}

			if(preg_match_all($reg, $content, $matches, PREG_SET_ORDER)){
				foreach($matches as $count => $match){
					foreach($match as $k => $v){
						$encodingFrom = mb_detect_encoding($v, array('ASCII', 'CP936', 'GB2312', 'GBK', 'BIG5'));
						if($encodingFrom){
							$v = mb_convert_encoding($v, $enCoding, $encodingFrom);
						}
						$matchesArr[$htmlTag][$count][$matchKey[$k]] = ($trimResult)? preg_replace('/\s{2,}/', ' ', $v) : $v;
					}
				}
			}
		}
		 
		return $matchesArr;
	}


	public static function infoEncryption($info, $isUrlParam = true)
	{
		$crypt = new Crypt();
		$crypt->setKey(self::getMessage('ENCRYPT-KEY'));
		$en = $crypt->encrypt($info, $crypt->getKey());
		if($isUrlParam){
			$en = urlencode($en);
		}
		return $en;
	}
	public static function infoDecryption($infoEn, $isUrlParam = true)
	{
		if($isUrlParam){
			$infoEn = urldecode($infoEn);
		}
		$crypt = new Crypt();
		$crypt->setKey(self::getMessage('ENCRYPT-KEY'));
		return $crypt->decrypt($infoEn, $crypt->getKey());
	}

	public static function accessCodeEntry()
	{
		YL_Security_Secoder::entry();
	}

	public static function accessCodeCheck($postCode)
	{
		return YL_Security_Secoder::check($postCode);
	}

	public static function getMessage($errorCode, $param = array())
	{
		if (null == self::$_msgs)
		{
			// Get the app config
			$dir = Q::ini("app_config");
			self::$_msgs = parse_ini_file($dir['APP_DIR']."/config/message.ini");
		}
		if (array_key_exists($errorCode, self::$_msgs))
		{
			$msg = self::$_msgs[$errorCode];
			if (is_string($param))
			{
				$msg = str_replace('{0}', $param, $msg);
			}
			else
			{
				foreach($param as $i => $value)
				{
					$msg = str_replace('{'.$i.'}', $value, $msg);
				}
			}
			return $msg;
		}
		else
		{
			return "";
		}
	}
	

	public static function delete_directory($dirname) {
		if (is_dir($dirname)){
			$dir_handle = opendir($dirname);
		}
		if (!$dir_handle){
			return false;
		}
		while($file = readdir($dir_handle)) {
			if ($file != "." && $file != "..") {
				if (!is_dir($dirname."/".$file)){
					unlink($dirname."/".$file);
				}else{
					self::delete_directory($dirname.'/'.$file);
				}
			}
		}
		closedir($dir_handle);
		rmdir($dirname);
		return true;
	}

	public static function getAddrTab()
	{
		$dir = Q::ini("app_config");
		return include $dir['APP_DIR']."/config/addressTab.php";
	}
	
	public static function getFileType($file)
	{
		@$imagetype = getimagesize($file);
	    switch(@$imagetype['mime']){
	        case 'image/gif':
	            $filetype = '.gif';
	            break;
	        case 'image/png':
	            $filetype = '.png';
	            break;
	        case 'image/bmp':
	            $filetype = '.bmp';
	            break;
	        case 'image/jpeg':
	            $filetype = '.jpg';
	            break;
	        default:
	        	$filetype = 'Unknown';
	    }
	    
	    return $filetype;
	}
	
	public static function getUploadifyFile()
	{
		if(!empty($_FILES['Filedata'])){
			return $_FILES['Filedata'];
		}
		
		return null;
	}

	public static function uploadingPhoto($user = null, $albumId = null, $fileInfo, $quality)
    {
        list($usec, $sec) = explode(" ", microtime());
        
    	$orignalFile = '';
    	if(isset($fileInfo['tmp_name'])){
			$tempFile = $fileInfo['tmp_name'];
			$targetPath = PHOTO_PATH;
		    $fileType = self::getFileType($tempFile);
		    if($fileType == 'Unknown'){
		    	$error = self::getMessage('UPLOAD-IMG-TYPE-ERROR');
		    	return array(
		    		'result' => false,
					'error' => $error
		    	);
		    }
	
		    $fileName = $usec.'_'.$sec.'_'.$user['id'].'_'.$albumId . $fileType;				//usec_sec_year_uid_day_albumid_month-sec_min_hour
		   	
		    $originalPath = $targetPath.'/orignal';
		    @mkdir($originalPath, 0777, true);
		    $orignalFile = $originalPath.'/'.$fileName;
		    //move_uploaded_file($tempFile, $orignalFile);
		    copy($tempFile, $orignalFile);
    	}
	    
    	if(is_readable($orignalFile)){
	    	$image = new Image();
			$image->createFromFile($orignalFile);
			if($image->save($orignalFile, $quality)){
				$orignalFileSize = filesize($orignalFile);
				if($image->getWidth() > PHOTO_THUMBNAIL_WIDTH){
		    		$image->resize(PHOTO_THUMBNAIL_WIDTH, -1);
		    	}
		    	$thumbnailPath = $targetPath.'/thumbnail';
			    @mkdir($thumbnailPath, 0777, true);
		    	$thumbnailFile = $thumbnailPath.'/'.$fileName;
				if(!$image->save($thumbnailFile, $quality)){
					$error = self::getMessage('SAVE-THUMBNAIL-PHOTO-ERROR');
				}				
			}
    	}else{
    		$error = self::getMessage('SAVE-ORIGINAL-PHOTO-ERROR');
    	}
    	
		if(empty($error)){
			return array(
				'result' => true,
				'fileName' => $fileName,
				'orignalFile' => $orignalFile,
				'orignalFileSize' => intval($orignalFileSize),
				'thumbnailFile' => $thumbnailFile
			);
		}else{
			return array(
				'result' => false,
				'error' => $error
			);
		}
    }
    
    public static function saveImgQueueTmp($img, $uid)
    {
    	$realImgs = array();
    	
    	$file = file_get_contents($img['src']);
    	
    	/*$url = $img['src'];
    	$ch = curl_init();
    	curl_setopt ($ch, CURLOPT_URL, $url);
    	curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); 
    	curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT,10);
    	$file = curl_exec($ch);
    	curl_close($ch);*/
    	
		if($file){
			list($usec, $sec) = explode(" ", microtime());
			
			$filename = explode('/', $img['src']);
			@mkdir(PHOTO_TMP, 0777, true);
			$filename = PHOTO_TMP . '/' . $uid . '_' . $usec . '_' . $sec . '_' . end($filename);
			if(file_put_contents($filename, $file)){
				$realImgs['tmp_name'] = $filename;
        	}
        }
    	
    	return $realImgs;
    }
    
    public static function GrabImage($url, $uid)   //same as function saveImgQueueTmp above
    {
    	if($url==""){
    		return false;
    	}
    	$realImgs = array();
    	
    	ob_start();
    	readfile($url['src']);
    	$img = ob_get_contents();
    	ob_end_clean();
    	
    	if($img){
    		list($usec, $sec) = explode(" ", microtime());
    		$filename = explode('/', $url['src']);
    		@mkdir(PHOTO_TMP, 0777, true);
    		$filename = PHOTO_TMP . '/' . $uid . '_' . $usec . '_' . $sec . '_' . end($filename);
    		$fp2 = @fopen($filename, "a");
    		if(fwrite($fp2, $img)){
    			$realImgs['tmp_name'] = $filename;
    		}
    	}
    	
    	return $realImgs;
    }
    
    public static function deleteSavedPhotos($photos, $key = 'fileName')
    {
    	if(!empty($photos)){
    		foreach($photos as $photo){
    			@unlink(PHOTO_PATH . '/orignal/' . $photo[$key]);
    			@unlink(PHOTO_PATH . '/thumbnail/' . $photo[$key]);
    		}
    	}
    }
    
    public static function processUploadifyPhoto($user = null, $albumId = null, $quality)
    {
    	$fileInfo = self::getUploadifyFile();
    	return self::uploadingPhoto($user, $albumId, $fileInfo, $quality);
    }
    
    public static function processGrabPhoto($user = null, $albumId = null, $quality)
    {
    	$imgQueue = $_POST['imgQueue'];
    	
    	if(empty($imgQueue)){
    		return array(
				'result' => false,
				'error' => self::getMessage('NO-SELECTED-IMG')
			);
    	}else if(count($imgQueue) > ONCE_SAVEGRABPHOTO_NUM){
    		return array(
				'result' => false,
				'error' => self::getMessage('TOO_MANY_PHOTO_SELECT')
			);
    	}else{
    		$ret = array('result' => true);
    		foreach($imgQueue as $k => $img){
    			$fileInfo = self::saveImgQueueTmp($img, $user['id']);
    			if(!empty($fileInfo)){
    				$ret['detail'][$k] = self::uploadingPhoto($user, $albumId, $fileInfo, $quality);
    				$ret['detail'][$k]['mark'] = $img['mark'];
    				@unlink($fileInfo['tmp_name']);
    			}
    		}
    		return $ret;
    	}
    }
    
	public static function randSession() {
    	$length=26;
    	$chars = "0123456789abcdefghijklmnopqrstuvwxyz";
    	$max = strlen($chars) - 1;
    	mt_srand((double)microtime() * 1000000);
    	$string = '';
    	for($i = 0; $i < $length; $i++) {
    		$string .= $chars[mt_rand(0, $max)];
    	}
    	return $string;
    }
    
    
	public static function traversalDirectoryFile($path, $filter = array(), $deep = 100)
	{
		$deep--;
		$rootList = array();
		$handle = opendir($path);
		while($file = readdir($handle)){
	  		if($file == '.' || $file == '..'){
	   			continue;
	  		}
	  		$newFilePath = $path . DIRECTORY_SEPARATOR . $file;
	  		$nodeArrTmp = $nodeArr = explode(DIRECTORY_SEPARATOR, $newFilePath);
	  		
	  		array_pop($nodeArrTmp);
	  		$parentNode = array_pop($nodeArrTmp);
	  		$node = $file = iconv('GB2312', 'UTF-8', end($nodeArr));
	  		
	  		if(!in_array($node, $filter)){
		  		if(is_dir($newFilePath)){
		  			$rootList[$node] = array();
		  			if($deep > 0){
			   			$rootList[$node] = self::traversalDirectoryFile($newFilePath, $filter, $deep);
		  			}
		  		}
		  		if(is_file($newFilePath)){
		  			$file = $node;
					$rootList[] = $file;
		  		}
	  		}
	 	}
	 	closedir($handle);
	 	
	 	return $rootList;
	}
	
	
	public static function RootListLevel1($rootList)
	{
		$level1 = array();
		foreach($rootList as $folder => $inFolder){
			if(is_array($inFolder)){
				$level1['folder'][] = $folder;
			}else{
				$level1['file'][] = $inFolder;
			}
		}
		
		return $level1;
	}
	
	public static function fileExtend($filename, $point = true)
	{
		$extend = explode("." , $filename);
		$va = count($extend)-1;
		return $point? '.'.$extend[$va] : $extend[$va];
	}
	
	public static function TimeFileName($filename, $preStr = '', $now = null)
	{
		if(empty($filename)){
			return '';
		}
		
		if($now === null){
			$now = time();
		}
		
		return $preStr . '_' . $now . self::fileExtend($filename);
		
	}
	
	public static function removePath($folder){
	    $files = glob( $folder . DIRECTORY_SEPARATOR . '*');
	    foreach( $files as $file ){
	        if($file == '.' || $file == '..'){continue;}
	        if(is_dir($file)){
	            $this->_remove_path( $file );
	        }else{
	            unlink( $file );
	        }
	    }
	    rmdir( $folder ); 
	}
	
	
}